﻿using System.Linq;
using System.Web.Mvc;
using AxeFrog.Security;

namespace AxeFrog.Web
{
	public enum RequiresRole
	{
		Any,
		Admin,
		Specific
	}

	/// <summary>
	/// Similar to the standard MVC Authorize attribute. Can be applied to individual actions or entire controllers.
	/// </summary>
	public class AuthenticateAttribute : ActionFilterAttribute
	{
		private readonly RequiresRole _requiresRole;
		private readonly long[] _requiredRoles;
		public AuthenticateAttribute()
		{
			_requiresRole = RequiresRole.Any;
			_requiredRoles = new long[0];
		}

		public AuthenticateAttribute(RequiresRole requireAdminRole)
		{
			_requiresRole = requireAdminRole;
			_requiredRoles = new long[0];
		}

		public AuthenticateAttribute(params long[] anyOfThese)
		{
			_requiresRole = RequiresRole.Specific;
			_requiredRoles = anyOfThese;
		}

		/// <summary>
		/// Indicates that a redirect should occur without a status message
		/// </summary>
		public bool Silent { get; set; }

		public override void OnActionExecuting(ActionExecutingContext filterContext)
		{
			if(RequestContext.CurrentUser.AccessLevel == AccessLevel.Anonymous)
			{
				if(Silent)
					filterContext.Result = BaseController.RerouteToLogin();
				else
					filterContext.Result = BaseController.RerouteToLogin("Please log in to access that area");
				return;
			}
			if(filterContext.RouteData.Values["action"].ToString().ToLower() != "CreatePassword" && RequestContext.CurrentUser.User.Password.Length == 0 || RequestContext.CurrentUser.User.DecryptPassword(WebsiteSettings.PrivateKey).Length == 0)
			{
				filterContext.Result = BaseController.RerouteToCreatePassword();
				return;
			}
			switch(_requiresRole)
			{
				case RequiresRole.Admin:
					if(RequestContext.CurrentUser.AccessLevel < AccessLevel.Administrator)
					{
						filterContext.Result = BaseController.RerouteToIndex("Only users with administrator priveleges can access that area");
						return;
					}
					break;

				case RequiresRole.Specific:
					if(RequestContext.CurrentUser.AccessLevel < AccessLevel.SuperUser && (from ur in RequestContext.CurrentUser.Roles
																						  join rr in _requiredRoles on ur equals rr
																						  select 1).Count() == 0)
					{
						filterContext.Result = BaseController.RerouteToIndex("You do not have the required permissions to access that area");
						return;
					}

					break;
			}
			base.OnActionExecuting(filterContext);
		}
	}
}